package cz.data.gateway.admin.mapstruct;

import com.fasterxml.jackson.core.type.TypeReference;
import cz.data.common.core.DataConstant;
import cz.data.common.support.mapstruct.EntityMapper;
import cz.data.common.utils.JsonCommon;
import cz.data.gateway.model.dto.GatewayRouteForm;
import cz.data.gateway.model.dto.GatewayRouteVo;
import cz.data.gateway.model.dto.FilterDefinitionDto;
import cz.data.gateway.model.dto.PredicateDefinitionDto;
import cz.data.gateway.model.dto.RouteDefinitionDto;
import cz.data.gateway.model.entity.GatewayRoute;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
public class GatewayRouteMapper implements EntityMapper<GatewayRouteForm, GatewayRoute, GatewayRouteVo> {
    private final TypeReference<List<PredicateDefinitionDto>> predicateReference = new TypeReference<List<PredicateDefinitionDto>>() {
    };
    private final TypeReference<List<FilterDefinitionDto>> filterReference = new TypeReference<List<FilterDefinitionDto>>() {
    };

    @Override
    public GatewayRouteForm toDTO(GatewayRoute route) {
        GatewayRouteForm form = new GatewayRouteForm();
        form.setId(route.getId());
        form.setRouteId(route.getRouteId());
        form.setUri(route.getUri());
        form.setPredicates(JsonCommon.parseObject(route.getPredicates(), predicateReference));
        form.setFilters(JsonCommon.parseObject(route.getFilters(), filterReference));
        form.setDescription(route.getDescription());
        form.setOrders(route.getOrders());
        form.setStatus(route.getStatus());
        form.setRemark(route.getRemark());
        return form;
    }

    @Override
    public List<GatewayRouteForm> toDTO(List<GatewayRoute> routes) {
        if (CollectionUtils.isEmpty(routes))
            return new ArrayList<>(0);
        return routes.stream().map(this::toDTO).collect(Collectors.toList());
    }

    @Override
    public GatewayRouteVo toVO(GatewayRoute route) {
        GatewayRouteVo routeVo = new GatewayRouteVo();
        routeVo.setId(route.getId());
        routeVo.setRouteId(route.getRouteId());
        routeVo.setUri(route.getUri());
        routeVo.setPredicates(JsonCommon.parseObject(route.getPredicates(), predicateReference));
        routeVo.setFilters(JsonCommon.parseObject(route.getFilters(), filterReference));
        routeVo.setDescription(route.getDescription());
        routeVo.setOrders(route.getOrders());
        routeVo.setStatus(route.getStatus());
        routeVo.setCreateBy(route.getCreateBy());
        routeVo.setCreateTime(route.getCreateTime());
        routeVo.setUpdateBy(route.getUpdateBy());
        routeVo.setUpdateTime(route.getUpdateTime());
        return routeVo;
    }

    @Override
    public List<GatewayRouteVo> toVO(List<GatewayRoute> routes) {
        if (CollectionUtils.isEmpty(routes))
            return new ArrayList<>(0);
        return routes.stream().map(this::toVO).collect(Collectors.toList());
    }

    @Override
    public GatewayRoute toEntity(GatewayRouteForm form) {
        GatewayRoute route = new GatewayRoute();
        route.setId(form.getId());
        route.setUri(form.getUri());
        route.setRouteId(form.getRouteId());
        route.setPredicates(JsonCommon.toJson(form.getPredicates()));
        route.setFilters(JsonCommon.toJson(form.getFilters()));
        route.setDescription(form.getDescription());
        route.setOrders(form.getOrders());
        route.setStatus(form.getStatus());
        route.setRemark(form.getRemark());
        return route;
    }

    @Override
    public List<GatewayRoute> toEntity(List<GatewayRouteForm> forms) {
        if (CollectionUtils.isEmpty(forms))
            return new ArrayList<>(0);
        return forms.stream().map(this::toEntity).collect(Collectors.toList());
    }

    public GatewayRoute toEntity(RouteDefinitionDto dto) {
        GatewayRoute route = new GatewayRoute();
        route.setId(dto.getId());
        route.setRouteId(dto.getRouteId());
        route.setUri(dto.getUri().toString());
        route.setOrders(dto.getOrder());
        route.setPredicates(JsonCommon.toJson(dto.getPredicates()));
        route.setFilters(JsonCommon.toJson(dto.getFilters()));
        Map<String, Object> metadata = dto.getMetadata();
        if (metadata.containsKey(RouteDefinitionDto.DEFINITION_NAME_KEY)) {
            Object value = metadata.get(RouteDefinitionDto.DEFINITION_NAME_KEY);
            route.setDescription(Objects.isNull(value) ? null : value.toString());
        } else {
            route.setDescription("未描述的路由");
        }
        if (metadata.containsKey(RouteDefinitionDto.STATUS_KEY)) {
            Object value = metadata.get(RouteDefinitionDto.STATUS_KEY);
            if (Boolean.TRUE.equals(value)) {
                route.setStatus(DataConstant.TrueOrFalse.TRUE.getKey());
            } else {
                route.setStatus(DataConstant.TrueOrFalse.FALSE.getKey());
            }
        } else {
            route.setStatus(DataConstant.TrueOrFalse.FALSE.getKey());
        }
        if (metadata.containsKey(RouteDefinitionDto.CREATOR_KEY)) {
            Object value = metadata.get(RouteDefinitionDto.CREATOR_KEY);
            String creator = Objects.isNull(value) ? null : value.toString();
            route.setCreateBy(creator);
            route.setUpdateBy(creator);
        }
        route.setCreateTime(LocalDateTime.now());
        route.setUpdateTime(LocalDateTime.now());
        return route;
    }

    public List<PredicateDefinitionDto> parsePredicates(String json) {
        return JsonCommon.parseObject(json, predicateReference);
    }

    public List<FilterDefinitionDto> parseFilters(String json) {
        return JsonCommon.parseObject(json, filterReference);
    }
}
